package com.wewins.fota.sys.filter;

import com.alibaba.fastjson.JSON;
import com.wewins.fota.bean.dto.ResponseRst;
import com.wewins.fota.common.constant.AuthConst;
import com.wewins.fota.common.constant.CommonConst;
import com.wewins.fota.common.constant.HttpConst;
import com.wewins.fota.sys.token.TokenManager;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.SignatureException;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.util.StringUtils;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;

public class TokenAuthenticationFilter extends BasicAuthenticationFilter {
    private TokenManager tokenManager;

    public TokenAuthenticationFilter(AuthenticationManager authenticationManager, TokenManager tokenManager) {
        super(authenticationManager);
        this.tokenManager = tokenManager;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        String token = request.getHeader(AuthConst.HTTP_HEADER_KEY_AUTHENTICATION);

        if (StringUtils.isEmpty(token)) {
            chain.doFilter(request, response);
            return;
        }
        String username;
        try {
            username = tokenManager.getUsernameFromToken(token);
            token = tokenManager.refreshToken(token);
        } catch (Exception e) {
            String errMsg;
            if (e instanceof ExpiredJwtException) {
                logger.error("current token has expired, please re-login:" + e.getMessage());
                errMsg = AuthConst.MSG_FAIL_TOKEN_EXPIRED;
            } else if (e instanceof SignatureException) {
                logger.error("server maybe restart, please reLogin!! err:" + e.getMessage());
                errMsg = AuthConst.MSG_FAIL_SIGNATURE_ERROR;
            } else {
                logger.error("Unknown exception:", e);
                errMsg = CommonConst.MSG_FAIL_UNKNOWN_ERROR;
            }
            response.setStatus(HttpConst.STATUS_OK);
            response.setContentType(MediaType.APPLICATION_JSON_VALUE);
            JSON.writeJSONString(response.getWriter(),
                    ResponseRst.builder()
                            .status(HttpConst.STATUS_FORBIDDEN)
                            .message(errMsg)
                            .build()
            );
            return;
        }
        UsernamePasswordAuthenticationToken authentication = StringUtils.isEmpty(username) ? null : new UsernamePasswordAuthenticationToken(username, token, new ArrayList<>());
        if (authentication != null) {
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }
        chain.doFilter(request, response);
    }
}
